package com.ifacebox.client.tools;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author znn
 */
public class FaceLuckDrawFrame extends JFrame implements ActionListener, MouseListener, AWTEventListener, FaceLuckDrawCountdownDialog.CountdownCallback {
    private static final long serialVersionUID = 1L;
    private final FaceLuckDrawConfig faceLuckDrawConfig;
    private final JPanel faceImagePanel;
    private JLabel[] faceImages;
    private JPopupMenu popup;
    private JMenuItem setup, exit;
    private TrayIcon trayIcon;
    private FaceImageImportProgressBar faceImageImportProgressBar;
    private FaceLuckDrawCountdownDialog faceLuckDrawCountdownDialog;
    private FaceLuckDrawSelectionDialog faceLuckDrawSelectionDialog;
    private FaceLuckDrawSetupDialog faceLuckDrawSetupDialog;
    private FaceImagePersonCache faceImagePersonCache;
    private ScheduledExecutorService scheduledExecutorService;
    private volatile boolean isFaceImageSwitch = true;

    public FaceLuckDrawFrame() {
        this(new FaceLuckDrawConfig());
    }

    public FaceLuckDrawFrame(FaceLuckDrawConfig faceLuckDrawConfig) {
        this.faceLuckDrawConfig = faceLuckDrawConfig;
        super.setTitle("幸运抽奖");
        super.setIconImage(new ImageIcon(this.getClass().getResource("/static/logo.png")).getImage());
        super.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        super.setLayout(new BorderLayout());
        super.setUndecorated(true);
        super.setSize(faceLuckDrawConfig.getScreenRectangle().width, faceLuckDrawConfig.getScreenRectangle().height);
        super.setPreferredSize(super.getSize());
        super.setLocation(faceLuckDrawConfig.getScreenRectangle().x, faceLuckDrawConfig.getScreenRectangle().y);
        super.add(this.faceImagePanel = new JPanel(), BorderLayout.CENTER);
        this.initComponent();
        super.pack();
        super.setResizable(false);
        super.setVisible(true);
        this.faceImagePersonFileLoad();
        this.faceImagePersonExecuteThread();
        this.faceImagePersonSelectionListener();
        this.addSystemTray();
    }

    /**
     * 初始化窗体组件
     */
    public void initComponent() {
        faceLuckDrawSetupDialog = new FaceLuckDrawSetupDialog(this, faceLuckDrawConfig);
        faceImageImportProgressBar = new FaceImageImportProgressBar(this, faceLuckDrawConfig);
        faceImagePanel.setComponentPopupMenu(popup = new JPopupMenu());
        faceImagePanel.setBackground(Color.WHITE);
        faceImagePanel.setLayout(new GridLayout(faceLuckDrawConfig.getFaceImageRows(), faceLuckDrawConfig.getFaceImageCols(), faceLuckDrawConfig.getFaceImageGap(), faceLuckDrawConfig.getFaceImageGap()));
        faceImages = new JLabel[faceLuckDrawConfig.getFaceImageTotal()];
        for (int i = 0; i < faceImages.length; i++) {
            faceImages[i] = new JLabel(faceLuckDrawConfig.getFaceImageIcon());
            faceImagePanel.add(faceImages[i]);
        }
        popup.add(setup = new JMenuItem("设置(S)"));
        setup.setMnemonic('S');
        setup.addActionListener(this);
        popup.add(exit = new JMenuItem("退出(X)"));
        exit.setMnemonic('X');
        exit.addActionListener(this);
    }

    public void addSystemTray() {
        if (SystemTray.isSupported()) {
            try {
                SystemTray.getSystemTray().add(trayIcon = new TrayIcon(super.getIconImage(), super.getTitle()));
            } catch (AWTException e) {
                throw new RuntimeException(e.getMessage(), e);
            }
            trayIcon.setImageAutoSize(true);
            trayIcon.addMouseListener(this);
            trayIcon.addActionListener(this);
        }
    }

    /**
     * 加载人脸照片与信息
     */
    public void faceImagePersonFileLoad() {
        faceImagePersonCache = new FaceImagePersonCache();
        File[] faceImageFile = faceLuckDrawConfig.getFaceImageFile();
        if (faceImageFile == null || faceImageFile.length == 0) {
            JOptionPane.showMessageDialog(this, "数据目录不存在或没有数据", super.getTitle(), JOptionPane.ERROR_MESSAGE);
            return;
        }
        faceImageImportProgressBar.setVisible(true);
        for (int i = 0; i < faceImageFile.length; i++) {
            FaceImagePerson faceImagePerson = new FaceImagePerson(faceImageFile[i], faceLuckDrawConfig);
            faceImagePersonCache.addFaceImagePerson(faceImagePerson);
            faceImageImportProgressBar.setValue(i + 1);
        }
        faceImageImportProgressBar.setVisible(false);
    }

    /**
     * 执行照片变换线程，每个照片一个线程
     */
    public void faceImagePersonExecuteThread() {
        scheduledExecutorService = Executors.newScheduledThreadPool(faceLuckDrawConfig.getFaceImageTotal());
        for (int i = 0; i < faceLuckDrawConfig.getFaceImageTotal(); i++) {
            JLabel faceImage = faceImages[i];
            scheduledExecutorService.scheduleAtFixedRate(() -> {
                FaceImagePerson faceImagePerson = null;
                if (isFaceImageSwitch) {
                    faceImagePerson = faceImagePersonCache.getRandomFaceImagePerson();
                    if (faceImagePerson == null || faceImagePerson.getFaceImage() == null) {
                        faceImage.setIcon(faceLuckDrawConfig.getFaceImageIcon());
                    }
                }
                if (faceImagePerson != null && faceImagePerson.getFaceImage() != null) {
                    faceImage.setIcon(faceImagePerson.getFaceImage());
                }
            }, faceLuckDrawConfig.getFaceImageSwitchMs(), faceLuckDrawConfig.getFaceImageSwitchMs(), TimeUnit.MILLISECONDS);
        }
    }

    /**
     * 抽奖按键监听
     */
    public void faceImagePersonSelectionListener() {
        faceLuckDrawCountdownDialog = new FaceLuckDrawCountdownDialog(this, faceLuckDrawConfig);
        faceLuckDrawSelectionDialog = new FaceLuckDrawSelectionDialog(this, faceLuckDrawConfig);
        faceImagePanel.addMouseListener(this);
        Toolkit.getDefaultToolkit().addAWTEventListener(this, AWTEvent.KEY_EVENT_MASK);
    }

    /**
     * 抽奖
     */
    public void faceLuckDraw(int faceLuckWin) {
        if (faceLuckDrawSelectionDialog.isVisible()) {
            faceLuckDrawSelectionDialog.setVisible(false);
            if (!faceLuckDrawConfig.isFaceImageLuckDrawSwitch()) {
                isFaceImageSwitch = true;
            }
        } else {
            faceLuckDrawCountdownDialog.faceLuckDrawCountdown(this, faceLuckWin);
        }
    }

    @Override
    public void onLuckDrawSelection(int faceLuckWin) {
        List<FaceImagePerson> faceImagePersons = faceImagePersonCache.getRandomFaceImagePerson(faceLuckDrawConfig.isFaceLuckWinRemove(), faceLuckWin);
        if (faceImagePersons == null) {
            JOptionPane.showMessageDialog(this, "没有中奖人数据", getTitle(), JOptionPane.ERROR_MESSAGE);
        } else {
            faceLuckDrawSelectionDialog.faceLuckDrawSelection(this, faceImagePersons);
            faceLuckDrawSelectionDialog.setVisible(true);
            if (!faceLuckDrawConfig.isFaceImageLuckDrawSwitch()) {
                isFaceImageSwitch = false;
            }
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == setup) {
            faceLuckDrawSetupDialog.setVisible(true);
        }
        if (e.getSource() == exit) {
            if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(this, "是否退出系统？", getTitle(), JOptionPane.YES_NO_OPTION)) {
                if (scheduledExecutorService != null) {
                    scheduledExecutorService.shutdown();
                }
                System.exit(0);
            } else {
                setVisible(false);
            }
        }
        if (e.getSource() == trayIcon) {
            setVisible(true);
        }
    }

    @Override
    public void mouseClicked(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
        if (e.getSource() == trayIcon && e.isPopupTrigger()) {
            popup.setLocation(e.getLocationOnScreen());
            popup.setInvoker(popup);
            popup.setVisible(true);
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        if (e.getSource() == trayIcon && e.isPopupTrigger()) {
            popup.setLocation(e.getLocationOnScreen());
            popup.setInvoker(popup);
            popup.setVisible(true);
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void eventDispatched(AWTEvent e) {
        if (e.getID() == KeyEvent.KEY_PRESSED) {
            KeyEvent evt = (KeyEvent) e;
            if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
                faceLuckDraw(1);
            }
            if (evt.getKeyCode() == KeyEvent.VK_F1) {
                faceLuckDraw(1);
            }
            if (evt.getKeyCode() == KeyEvent.VK_F2) {
                faceLuckDraw(2);
            }
            if (evt.getKeyCode() == KeyEvent.VK_F3) {
                faceLuckDraw(3);
            }
            if (evt.getKeyCode() == KeyEvent.VK_F4) {
                faceLuckDraw(4);
            }
            if (evt.getKeyCode() == KeyEvent.VK_F5) {
                faceLuckDraw(5);
            }
            if (evt.getKeyCode() == KeyEvent.VK_F6) {
                faceLuckDraw(6);
            }
            if (evt.getKeyCode() == KeyEvent.VK_F7) {
                faceLuckDraw(7);
            }
            if (evt.getKeyCode() == KeyEvent.VK_F8) {
                faceLuckDraw(8);
            }
            if (evt.getKeyCode() == KeyEvent.VK_F9) {
                faceLuckDraw(9);
            }
            if (evt.getKeyCode() == KeyEvent.VK_F10) {
                faceLuckDraw(10);
            }
        }
    }

    public static void main(String[] args) throws Exception {
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
            StringWriter stringWriter = new StringWriter();
            e.printStackTrace(new PrintWriter(stringWriter));
            JOptionPane.showMessageDialog(null
                    , new JScrollPane(new JTextArea(stringWriter.toString(), 10, 0))
                    , t.toString()
                    , JOptionPane.ERROR_MESSAGE);
        });
        new FaceLuckDrawFrame();
    }
}
